package com.hanter.android.radlib.bitmap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.net.Uri;

import androidx.annotation.Nullable;
import androidx.exifinterface.media.ExifInterface;

import com.hanter.android.radlib.util.AndroidUriUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;

public class BitmapUtils {

    @Nullable
    public static BitmapFactory.Options getBitmapOptions(Context context, Uri uri) throws FileNotFoundException {
        InputStream is = AndroidUriUtils.getInputStream(context, uri);
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Rect rect = new Rect();
        BitmapFactory.decodeStream(is, rect, options);
        return options;
    }

    @SuppressWarnings("JavaReflectionMemberAccess")
    public static void setBitmapDefaultDensity(int density) {
        try {
            Class clazz = Class.forName("android.graphics.Bitmap");
            Field field = clazz.getDeclaredField("sDefaultDensity");
            field.setAccessible(true);
            field.set(null, density);
            field.setAccessible(false);
        } catch (IllegalAccessException | NoSuchFieldException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static int getSampleSize(int srcWidth, int srcHeight,
                              int destWidth, int destHeight,
                              int maxWidth, int maxHeight) {
        int inSampleSize = 1;
        if (srcHeight > maxWidth || srcWidth > maxHeight) {
            final int halfHeight = srcHeight / 2;
            final int halfWidth = srcWidth / 2;
            while ((halfHeight / inSampleSize) > destHeight
                    && (halfWidth / inSampleSize) > destWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

    public static int getSampleSize(int srcWidth, int srcHeight,
                              int destWidth, int destHeight) {
        return getSampleSize(srcWidth, srcHeight, destWidth, destHeight,
                Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    @Nullable
    public static Bitmap doSample(Context context, Uri uri, int maxWidth, int maxHeight) {
        InputStream is;
        try {
            is = AndroidUriUtils.getInputStream(context, uri);
            if (is == null)
                return null;
        } catch (FileNotFoundException e) {
            return null;
        }

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Rect rect = new Rect();
        BitmapFactory.decodeStream(is, rect, options);

        if (options.outWidth == 0) {
            return null;
        }

        try {
            Bitmap outBitmap;
            is.close();

            // 必须重新获取，否则decode返回空。如果用is.reset()并不起作用，还报错。
            is = context.getContentResolver().openInputStream(uri);
            if (is == null)
                return null;

            boolean sample = true;

            if (sample) {
                int imageWidth = options.outWidth; // 图片原宽度
                int imageHeight = options.outHeight; // 图片原高度

                int dstWidth, dstHeight;
                if (imageWidth > imageHeight) {
                    dstWidth = Math.min(imageWidth, maxWidth);
                    dstHeight = (dstWidth * imageHeight) / imageWidth;
                } else {
                    dstHeight = Math.min(imageHeight, maxHeight);
                    dstWidth = (imageWidth * dstHeight) / imageHeight;
                }
                int inSampleSize = getSampleSize(imageWidth, imageHeight, dstWidth, dstHeight);


                BitmapFactory.Options sampleOptions = new BitmapFactory.Options();
                sampleOptions.inSampleSize = inSampleSize;
                sampleOptions.inJustDecodeBounds = false;

                float scaleX = (float) dstWidth / (float) (imageWidth / inSampleSize);
                float scaleY = (float) dstHeight / (float) (imageHeight / inSampleSize);

                if (scaleX >= 1.0f && scaleY >= 1.0f) {
                    sampleOptions.inSampleSize = 1;
                    scaleX = 1.0f;
                    scaleY = 1.0f;
                }

                Matrix mat = new Matrix();
                mat.postScale(scaleX, scaleY);

                Bitmap bitmap = BitmapFactory.decodeStream(is, rect, sampleOptions);

                if (bitmap == null) {
                    return null;
                }

                ExifInterface ei = new ExifInterface(is);

                int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                        ExifInterface.ORIENTATION_NORMAL);
                switch (orientation) {
                    case ExifInterface.ORIENTATION_ROTATE_90:
                        mat.postRotate(90);
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_180:
                        mat.postRotate(180);
                        break;
                }

                outBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                        mat, true);
            } else {
                options.inJustDecodeBounds = false;
                outBitmap = BitmapFactory.decodeStream(is, rect, options);
            }

            return outBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
